#ifndef EGG_GPUPARAMMAP_H
#define EGG_GPUPARAMMAP_H

#include "GPUProgram.h"
#include "Texture2D.h"
#include "TextureCube.h"

namespace egg{

    class GPUParamMap{
        typedef map<string,GPUParamPtr> ParamMap;
        typedef pair<GLint,GPUParam*> ParamSlot;
        typedef vector<ParamSlot> ParamList;
    public:
        GPUParamMap(GPUProgramPtr _program);
        ~GPUParamMap();
        void activate();
        void bindParam(GPUParamPtr _param);
        NumericParamPtr getNumericParam(const string& _name);
        TextureParamPtr getTextureParam(const string& _name);

        inline GPUProgramPtr getProgram(){
            return mProgram;
        }
        inline void setParam(const string& _name,float _param){
            getNumericParam(_name)->set(_param);
        }
        inline void setParam(const string& _name,int32 _param){
            getNumericParam(_name)->set(_param);
        }
        inline void setParam(const string& _name,const vec2& _param){
            getNumericParam(_name)->set(_param);
        }
        inline void setParam(const string& _name,const vec3& _param){
            getNumericParam(_name)->set(_param);
        }
        inline void setParam(const string& _name,const vec4& _param){
            getNumericParam(_name)->set(_param);
        }
        inline void setParam(const string& _name,const mat2& _param){
            getNumericParam(_name)->set(_param);
        }
        inline void setParam(const string& _name,const mat3& _param){
            getNumericParam(_name)->set(_param);
        }
        inline void setParam(const string& _name,const mat4& _param){
            getNumericParam(_name)->set(_param);
        }
        inline void setParam(const string& _name,Texture2DPtr _param){
            getTextureParam(_name)->mTexture=_param;
        }
    protected:
        template<class T>
        shared_ptr<T> getParam(const string& _name){
            ParamMap::iterator itr=mAllParams.find(_name);
            if(itr!=mAllParams.end()){
                return static_pointer_cast<T>(itr->second);
            }else{
                return shared_ptr<T>(0);
            }
        }

        void updateActiveParams();
        void addActiveParam(GPUParam* _param);
    protected:
        int32 mVersion;
        GPUProgramPtr mProgram;
        ParamMap mAllParams;
        ParamList mNumerics;
        ParamList mTextures;
    };

}

#endif